﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;


namespace GeoPlugIn
{
    /// <summary>
    /// Reader for 3 CSV documents hilding municipalities hierarchy history
    /// </summary>
    public class HgdeHistory : IReader
    {
        //-------------------------------------------------------------------
        #region Internal Members

        private StreamReader sr;
        private string line;
        private string initialDirectory;
        private int maxMutationDistrict;
        private int maxMutationMunicipality;

        private Dictionary<string, CsvCanton> cantonDico;
        private Dictionary<string, CsvDistrict> districtDico ;
        private List<CsvMunicipality> municipalityList;

        #endregion // Internal Members

        //-------------------------------------------------------------------
        #region Properties

        public static string[] ArrayAliasRef = { "KT", "BEZ", "GDE" };
        private string compressDate;

        public string Diagnostic
        {
            get;
            set;
        }
        
        public string VersionDate
        {
            get;
            set;
        }

        public string VersionSdmx
        {
            get;
            set;
        }


        public Dictionary<string, CsvCanton> CantonDico
        {
            get { return cantonDico; }
        }

        public Dictionary<string, CsvDistrict> DistrictDico
        {
            get { return districtDico; }
        }

        public List<CsvMunicipality> MunicipalityList
        {
            get { return municipalityList; }
        }

        public string InitialDirectory
        {
            get { return initialDirectory; }
        }

        public string DefaultCantonPath
        {
            get { return initialDirectory + compressDate + "_GDEHist_" + ArrayAliasRef[0] + ".txt"; }
        }
        public string DefaultDistrictPath
        {
            get { return initialDirectory + compressDate + "_GDEHist_" + ArrayAliasRef[1] + ".txt"; }
        }
        public string DefaultMunicipalityPath
        {
            get { return initialDirectory + compressDate + "_GDEHist_" + ArrayAliasRef[2] + ".txt"; }
        }

        public int MaxMutationDistrict
        {
            get { return maxMutationDistrict; }
        }
        public int MaxMutationMunicipality
        {
            get { return maxMutationMunicipality; }
        }

        #endregion //Properties

        #region Constructor

        public HgdeHistory(string path)
        {
            cantonDico = new Dictionary<string, CsvCanton>();
            districtDico = new Dictionary<string, CsvDistrict>();
            municipalityList = new List<CsvMunicipality>();

            VersionSdmx = DateTime.Now.Year.ToString() + ".1"; // Approximate
            Diagnostic = string.Empty;

            // Path name as folder\YYYYMMDD_GDEHist_(typ).txt  3 files expected
            initialDirectory = Path.GetDirectoryName(path);
            if (initialDirectory[initialDirectory.Length - 1] != '\\')
                initialDirectory += "\\";

            try
            {
                compressDate = Path.GetFileName(path).Substring(0, 8);
                string year = Path.GetFileName(path).Substring(0, 4);
                string month = Path.GetFileName(path).Substring(4, 2);
                string day = Path.GetFileName(path).Substring(6, 2);
                DateTime dt = new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), Convert.ToInt32(day));
                VersionDate = dt.ToString("yyyy-MM-dd");
            }
            catch
            {
                throw new ApplicationException("Unable to get validity date from filename!");
            }

        }
        #endregion

        /// <summary>
        /// Read and tests. On exception, conserve info in Diagnostic
        /// </summary>
        /// <returns>True on error</returns>
        public bool ValidatePreConditions()
        {
            try
            {
                Diagnostic = string.Empty;
            LoadFromCsv(DefaultCantonPath, DefaultDistrictPath, DefaultMunicipalityPath);
            }
            catch (Exception ex)
            {
                string msg = ex.Message + Environment.NewLine;
                if (ex.InnerException != null)
                    msg += ex.InnerException.Message;
                Diagnostic = msg;
            }

            return Diagnostic.Length > 0;
        }

        private int UpdateMaxMutationNo(int mutNo, Mutation mut)
        {
            if (string.IsNullOrEmpty(mut.No) == false)
            {
                mutNo = Math.Max(mutNo, Convert.ToInt32(mut.No));
            }
            return mutNo;
        }


        private void LoadFromCsv(string cantonPath, string districtPath, string municipalityPath)
        {
            maxMutationDistrict = maxMutationMunicipality = 0;

            cantonDico.Clear();
            using (sr = new StreamReader(cantonPath, Encoding.Default))
            {
                while ((line = sr.ReadLine()) != null)
                {
                    CsvCanton aCanton = new CsvCanton(line);
                    cantonDico.Add(aCanton.Code, aCanton);
                }

            }
            if (cantonDico.Count == 0)
            {
                throw new ApplicationException("Canton information required for district.");
            }

            districtDico.Clear();
            using (sr = new StreamReader(districtPath, Encoding.Default))
            {
                while ((line = sr.ReadLine()) != null)
                {
                    CsvDistrict aDistrict = new CsvDistrict(line);
                    aDistrict.Canton = cantonDico[aDistrict.CantonCode];
                    maxMutationDistrict = UpdateMaxMutationNo(maxMutationDistrict, aDistrict.Inscription);
                    maxMutationDistrict = UpdateMaxMutationNo(maxMutationDistrict, aDistrict.Radiation);
                    districtDico.Add(aDistrict.NoHistory, aDistrict);
                }
            }

            if (districtDico.Count == 0)
            {
                throw new ApplicationException("District information required for Municipalities.");
            }

            municipalityList.Clear();
            using (sr = new StreamReader(municipalityPath, Encoding.Default))
            {
                while ((line = sr.ReadLine()) != null)
                {
                    CsvMunicipality aMunicipality = new CsvMunicipality(line);
                    aMunicipality.District = districtDico[aMunicipality.NoHistoryDistrict];
                    maxMutationMunicipality = UpdateMaxMutationNo(maxMutationMunicipality, aMunicipality.Inscription);
                    maxMutationMunicipality = UpdateMaxMutationNo(maxMutationMunicipality, aMunicipality.Radiation);

                    municipalityList.Add(aMunicipality);
                }
            }
        }
    }
}
